#include "bluezmanager.h"
#include "bluezagent.h"

#include <KF5/BluezQt/bluezqt/manager.h>
#include <KF5/BluezQt/bluezqt/adapter.h>
#define BLUEZ_DEV_NAME "XADBluetooth"

class BluezManager::BluezManagerPrivate: public QObject
{
public:
    explicit BluezManagerPrivate(QObject* parent): QObject(parent) {}
    BluezQt::ManagerPtr manager{nullptr};
    BluezQt::InitManagerJob* initJob{nullptr};
    BluezAgent* agent{nullptr};
    BluezQt::AdapterPtr adapter{nullptr};
    bool power;
    struct DeviceState
    {
        QString address;//这里只关注单个设备的状态
        bool connected;
    } captureDevice;
};

BluezManager::BluezManager(BluezQt::ManagerPtr manager, QObject* parent):
    QObject(parent),
    d_ptr(new BluezManagerPrivate(this))
{
    d_ptr->manager = manager;
    d_ptr->manager->rfkill()->unblock();
    d_ptr->initJob = d_ptr->manager->init();
    d_ptr->initJob->start();
    connect(d_ptr->initJob, &BluezQt::InitManagerJob::result, this, &BluezManager::initJobFinished);
    // BluezQt::PendingCall* startCall = BluezQt::Manager::startService();
    //connect(startCall, &BluezQt::PendingCall::finished, this, &BluezManager::startServerFinished);
}

void BluezManager::startServerFinished(BluezQt::PendingCall* call)
{
    auto result = call->value().toUInt();
    if(result == 1 || result == 2)
    {
        d_ptr->initJob = d_ptr->manager->init();
        d_ptr->initJob->start();
        connect(d_ptr->initJob, &BluezQt::InitManagerJob::result, this, &BluezManager::initJobFinished);
    }
    else
    {
        // "An error occurred while starting the org.bluez service.";
    }
}

void BluezManager::initJobFinished(BluezQt::InitManagerJob* job)
{
    if(job->error())
    {
        qDebug("Job init err:%s", job->errorText().toLocal8Bit().data());
    }
    //注册agent
    d_ptr->agent = new BluezAgent(this);
    BluezQt::PendingCall* agentRegister =  d_ptr->manager->registerAgent(d_ptr->agent);
    connect(agentRegister, &BluezQt::PendingCall::finished, this, [this](BluezQt::PendingCall * call)
    {
        if(call->error() == BluezQt::PendingCall::InvalidArguments)
        {
            qDebug("register anget err: invalid arguments");
        }
        else
        {
            d_ptr->manager->requestDefaultAgent(d_ptr->agent);
        }
    });
    connect(d_ptr->agent, &BluezAgent::acceptDevice, this, &BluezManager::setCaptureAddress);
    //初始化adapter
    auto adapters = d_ptr->manager->adapters();
    d_ptr->adapter = adapters.first();//d_ptr->manager->usableAdapter();
    if(d_ptr->adapter.isNull())
    {
        qWarning("Not find adapter");
        return;
    }
    if(d_ptr->adapter->name() != BLUEZ_DEV_NAME)
    {
        d_ptr->adapter->setName(BLUEZ_DEV_NAME);
    }
    connect(d_ptr->adapter.data(), &BluezQt::Adapter::poweredChanged, this, &BluezManager::powerChanged);
    connect(d_ptr->adapter.data(), &BluezQt::Adapter::deviceChanged, this, &BluezManager::deviceChanged);

    emit setAdapterName(d_ptr->adapter->name());
    //默认开启电源
    d_ptr->power = d_ptr->adapter->isPowered();
    emit switchPower(d_ptr->power);
    if(!d_ptr->power)
    {
        d_ptr->adapter->setPowered(true);
    }
#ifdef BLUEZQT_GUI
    else
    {
        enablePairing();
        startDiscovery();
    }
#endif
}

void BluezManager::powerChanged(bool powered)
{
    d_ptr->power = powered;
    emit switchPower(d_ptr->power);
#ifdef BLUEZQT_GUI
    //gnome 桌面蓝牙是在开启后就开始扫描
    if(d_ptr->power)
    {
        enablePairing();
        startDiscovery();
    }
    else
    {
        stopDiscovery();
        //disablePairing();
    }
#endif
}

void BluezManager::deviceChanged(BluezQt::DevicePtr device)
{
    if(d_ptr->captureDevice.address ==  device->address() &&
            d_ptr->captureDevice.connected != device->isConnected())
    {
        d_ptr->captureDevice.connected = device->isConnected();
        emit deviceConnected( d_ptr->captureDevice.connected);
        if(d_ptr->captureDevice.connected)
        {
            qDebug("link");
        }
        else
        {
            qDebug("dislink");
        }
    }
//    else
//    {
//        qDebug("device change name:%s address:%s connected:%d paired:%d", device->name().toLocal8Bit().data(),
//               device->address().toLocal8Bit().data(),
//               device->isConnected(),
//               device->isPaired());
//    }
}

void BluezManager::setCaptureAddress(const QString& address, bool connected)
{
    d_ptr->captureDevice = {address, connected};
}

void BluezManager::clickPower()
{
    if(d_ptr->adapter)
    {
        d_ptr->adapter->setPowered(!d_ptr->power);
    }
}

void BluezManager::enablePairing()
{
    if(d_ptr->adapter)
    {
        d_ptr->adapter->setDiscoverable(true);
        d_ptr->adapter->setPairable(true);
    }
}

void BluezManager::disablePairing()
{
    if(d_ptr->adapter)
    {
        d_ptr->adapter->setDiscoverable(false);
        d_ptr->adapter->setPairable(false);
    }
}

void BluezManager::startDiscovery()
{
    if(d_ptr->adapter && !d_ptr->adapter->isDiscovering())
    {
        d_ptr->adapter->startDiscovery();
        //qDebug("statrt discover");
    }
}

void BluezManager::stopDiscovery()
{
    if(d_ptr->adapter && d_ptr->adapter->isDiscovering())
    {
        d_ptr->adapter->stopDiscovery();
        //qDebug("stop discover");
    }
}

void BluezManager::removeDevice(BluezQt::DevicePtr device)
{
    if(d_ptr->adapter)
    {
        d_ptr->adapter->removeDevice(device);
    }
}
